import serial
import time
import os
import sys
import random
import re
import subprocess
import threading

# 定义常量
DEBUG_PORT = "COM4"
AT_PORT = "COM39"
BAUDRATE = 115200

# 定义变量
at_serial = None
debug_serial = None

# 记录运行次数
runTimes = 0

# log文件
DEBUG_LOG = ""
ADB_LOG = ""
AT_LOG = ""

# 创建日志文件
def createLogFile():
    global DEBUG_LOG, ADB_LOG, AT_LOG
    timestamp = time.strftime("%Y-%m-%d_%H_%M_%S", time.localtime())
    DEBUG_LOG = f"DEBUG_LOG_{timestamp}.log"
    ADB_LOG = f"ADB_LOG_{timestamp}.log"
    AT_LOG = f"AT_LOG_{timestamp}.log"
    
    with open(DEBUG_LOG, 'w', encoding='utf-8') as file:
        file.write("DEBUG 日志开始记录...\n")
    
    with open(ADB_LOG, 'w', encoding='utf-8') as file:
        file.write("ADB 日志开始记录...\n")
        
    with open(AT_LOG, 'w', encoding='utf-8') as file:
        file.write("AT 日志开始记录...\n")

# 写日志
def write_log(log, logFile):
    with open(logFile, 'a', encoding='utf-8') as file_object:
        file_object.write(str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "\r\n" + log + "\r\n")

# 发送at指令
def at_write(command, timeout, DEBUG_PORT_opened, at_result, RDY=0, CPIN=0):
    write_log(str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())), DEBUG_LOG)
    at_command = command.encode("UTF-8")
    DEBUG_PORT_opened.write(at_command)

# 读取at口返回
def at_read(serial_port, logFile=""):
    rec_str = ''
    while True:
        time.sleep(1)
        lenth = serial_port.inWaiting()
        if lenth > 0:
            rec_str = serial_port.read(size=lenth)
            try:
                rec_str = re.sub('\\x1b.*?m', "", rec_str.decode("UTF-8"), 0, re.I)
                if logFile != "":
                    with open(logFile, 'a') as file_object:
                        rec_str = str(time.time()) + ":" + str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "\r\n" + rec_str
                        file_object.write(str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + "\r\n" + rec_str + "\r\n")
                return rec_str
            except:
                return ""
        else:
            break
    return rec_str

# 登录设备
def loginDevice():
    global DEBUG_LOG
    while True:
        print("等待登录... ... ")
        time.sleep(3)
        at_write("\r\n", 3, debug_serial, "OK")
        result = at_read(debug_serial)

        with open(DEBUG_LOG, 'a') as file_object:
            file_object.write(result)

        if "login:" in result:
            at_write("root\r\n", 3, debug_serial, "OK")
            print("账号输入成功")
            time.sleep(2)
            at_write("oelinux123\r\n", 3, debug_serial, "OK")
            print("密码输入成功")
        elif "~ #" in result:
            print("登录成功")
            at_write("echo 2 >/proc/sys/kernel/printk\r\n", 3, debug_serial, "OK")
            break
        else:
            continue

# 检查debug口通信状态
def check_port_status():
    global debug_serial
    if debug_serial is None:
        try:
            debug_serial = serial.Serial(DEBUG_PORT, BAUDRATE)
        except:
            print("at口连接失败，请检查端口")
            sys.exit()

# 写入运行次数到日志
def writeRuntimesToLog():
    global runTimes
    with open(DEBUG_LOG, 'a+') as file_object:
        file_object.write("\r\n{} runtimes: {} {}\r\n".format("<"*20, runTimes, ">"*20))
    print("\r\n{} runtimes: {} {}\r\n".format("<"*20, runTimes, ">"*20))
    runTimes += 1

# 进入测试接口
def intoTestInterface_testsdk(debug_serial, logFile):
    at_write("cd /data\r\n./test_sdk_api\r\n", 3, debug_serial, "OK")
    result = at_read(debug_serial, logFile)

# 退出测试接口
def exit_testsdk(debug_serial, logFile):
    at_write("-1\n-1\n", 3, debug_serial, "OK")
    result = at_read(debug_serial, logFile)

# 返回测试接口
def back_testsdk(debug_serial, logFile):
    at_write("-1\n", 3, debug_serial, "OK")
    result = at_read(debug_serial, logFile)

# 设置at指令
def set_at_command(command):
    ser = serial.Serial(AT_PORT, BAUDRATE)
    ser.write((command + "\r\n").encode())
    ser.write(("\r\n").encode())
    time.sleep(2)
    response_qmssr = ser.read_all().decode()
    ser.close()
    write_log(f"at指令{command}执行结果:{response_qmssr}", AT_LOG)
    if 'OK' in response_qmssr:
        write_log(f"at指令{command}执行成功", AT_LOG)
    else:
        write_log(f"at指令{command}执行失败", AT_LOG)

# 配置路由
def config_route():
    at_write("ip route add default via 100.74.209.62 dev rmnet_data0\r\n", 3, debug_serial, "OK")
    time.sleep(1)
    at_write("iptables -t nat -A POSTROUTING -o rmnet_data0 -j MASQUERADE --random\r\n", 3, debug_serial, "OK")
    time.sleep(1)
    at_write("echo 'nameserver 61.132.163.68'>> /tmp/ql_lan_resolv.conf\r\n", 3, debug_serial, "OK")
    time.sleep(1)
    at_write("echo 'nameserver 202.102.213.68'>> /etc/resolv.conf\r\n", 3, debug_serial, "OK")
    at_write("cat /tmp/ql_lan_resolv.conf\r\n", 3, debug_serial, "OK")
    time.sleep(1)
    at_write("cat /etc/resolv.conf\r\n", 3, debug_serial, "OK")
    result = at_read(debug_serial)
    if "nameserver 61.132.163.68" in result and "nameserver 202.102.213.68" in result:
        print("路由配置成功")
    else:
        print("路由配置失败")
        sys.exit()

# 模组一直ping外网，不中断
def run_adb_ping_command(host, interval=5):
    try:
        while True:
            result = subprocess.run(['adb', 'shell', 'ping', '-c', '4', host], capture_output=True, text=True, check=True)
            output = result.stdout
            write_log(output, ADB_LOG)
            if "0% packet loss" in output:
                write_log("Ping 成功", ADB_LOG)
            else:
                write_log("Ping 失败 or 数据包丢失", ADB_LOG)
            time.sleep(interval)
    except subprocess.CalledProcessError as e:
        print(e.stderr)

# 执行WiFi扫描
def wf_report_scan():
    scan_count = 0
    success_count = 0
    failure_count = 0
    intoTestInterface_testsdk(debug_serial, DEBUG_LOG)
    time.sleep(1)
    at_write("10\r\n", 3, debug_serial, "OK")
    time.sleep(2)
    at_write("0\r\n", 3, debug_serial, "OK")
    time.sleep(2)
    at_write("3\r", 3, debug_serial, "OK")  
    time.sleep(2)
    at_write("6\r", 3, debug_serial, "OK")
    time.sleep(2)
    write_log("开启扫描上报", DEBUG_LOG)
    at_write("43\r", 3, debug_serial, "OK")
    time.sleep(2)
    while True:
        write_log("开始扫描", DEBUG_LOG)
        at_write("44\r", 3, debug_serial, "OK")  
        scan_count += 1
        result = at_read(debug_serial, DEBUG_LOG)
        if "Successful" in result:
            success_count += 1
        else:
            failure_count += 1
        write_log(f"扫描结果: {result}", DEBUG_LOG)
        write_log(f"扫描次数: {scan_count}, 成功次数: {success_count}, 失败次数: {failure_count}", DEBUG_LOG)
        time.sleep(5)

# 模块拨号
def nw_data_call():
    at_write("ql_net_test call rmnet_data0\r\n", 3, debug_serial, "OK")
    print("模组拨号完成")

# 主程序
if __name__ == '__main__':
    check_port_status()
    createLogFile()  # 确保日志文件被创建

    # 打印日志路径，确认日志文件已创建
    print(f"DEBUG_LOG: {DEBUG_LOG}, ADB_LOG: {ADB_LOG}, AT_LOG: {AT_LOG}")

    loginDevice()
    time.sleep(5)

    write_log("****************开始测试**************", DEBUG_LOG)  # 确保日志路径不为空
    set_at_command('AT+CREG?;+CGREG?;+CEREG?;+C5GREG?;+COPS?;+QCSQ;+QNWINFO')
    nw_data_call()
    config_route()
    print("配置成功，启动线程，开始执行WiFi扫描同时模组一直ping外网")
    # 启动线程
    ping_thread = threading.Thread(target=run_adb_ping_command, args=("www.baidu.com",))
    scan_thread = threading.Thread(target=wf_report_scan)
    ping_thread.start()
    scan_thread.start()
    ping_thread.join()
    scan_thread.join()
